package webserver;

import java.io.*;
import java.util.*;
import javax.activation.*;


/**
 *In dieser Klasse werden die Webseiten gelesen sowie die Content länge der abzurufenden
 * Seite ausgegeben. Auch Fehlerbehandlungen werden hier an die Klasse ErrorExeption weitergegeben.
 * @author Frederik Gagel
 * @brief Klasse FileManager
 */
public class FileManager {

    private String fileName;
    private final String WORK_DIR;
    private File fileToRead;
    private int contentLength = 0;
    private byte[] contentBytes = null;
    private String mimeType = new String();
    private String errorCode = "";


    /**
     * Konstruktor der Klasse. Initialisierung der Variablen mit
     * vordefinierten Werten.
     * @param path
     */
    public FileManager(String path){
        WORK_DIR = Server.getInstance().getWebDir();
        fileName = WORK_DIR + "/" + path.trim();
        fileToRead = new File(fileName);
    }

   /**
    *
    * Liest den Inhalt der angeforderten Seite. Im Fehlerfall wird dieser in der Fehlerroutine
    * behandelt.
    * @return contentBytes = bytes[]
    */
    public byte[] readFile(){

        try {

           BufferedInputStream buffInput = new BufferedInputStream(new FileInputStream(fileToRead));

           byte[] fileBytes = new byte[buffInput.available()];
           buffInput.read(fileBytes);
           buffInput.close();

           contentLength = fileBytes.length;
           contentBytes = fileBytes;
           setErrorCode(200);

           setContentType();

           return contentBytes;

        }

        catch(FileNotFoundException fnfex){
                setErrorCode(404);
                contentBytes = readErrorFile("404");
        }


        catch(IOException ex) {
                setErrorCode(500);
                contentBytes = readErrorFile("500");

        }

        return contentBytes;

    }

    /**
     * Abfrage des Typs der angeforderten Datei.
     */

    private void setContentType(){

        // http://java.sun.com/javase/6/docs/api/javax/activation/MimetypesFileTypeMap.html
        MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();

        //mimetype "image/png" is missing in MimetypeFileTypeMap...
        mimeTypesMap.addMimeTypes("image/png PNG");
        mimeTypesMap.addMimeTypes("image/png png");

        mimeType = mimeTypesMap.getContentType(fileToRead);

        if(mimeType.equals("application/octet-stream")){
            setErrorCode(415);
            contentBytes = readErrorFile("415");
        }

    }

    /**
     * Prüft das Mofifikationsdatum der angeforderten Seite und gibt dieses zurück.
     * @return Date
     */

    public Date getLastModified() {
        return new Date(fileToRead.lastModified());
    }

    /**
     * Überprüfung des types der Seite.
     * @return mimeType = String
     */

    public String getMIMEType(){
        return mimeType;
    }

    /**
     * Rückgabe der Länge der angeforderten Seite.
     * @return
     */
    public int getContentLength(){
        return contentLength;
    }

    /**
     * Setzen eines Errorwertes und Aufruf der Klasse errorCode.
     * @param code
     */
    private void setErrorCode(int code){
        errorCode = Status.getInstance().getStatusCode(code);
    }

    /**
     * Rückgabe des aktuellen Errors.
     * @return Error
     */
    public String getErrorCode() {
        return errorCode;
    }
    /**
     * Lesen der Fehler Files in Form von HTML Dokumenten.
     * @param error
     * @return ResponseBody
     */

    public byte[] readErrorFile(String error){

        File errorFile = new File("bin/" + error + ".html");
        contentBytes = "".getBytes();

        try {

           BufferedInputStream buffInput = new BufferedInputStream(new FileInputStream(errorFile));

           byte[] fileBytes = new byte[buffInput.available()];
           buffInput.read(fileBytes);
           buffInput.close();

           contentLength = fileBytes.length;
           contentBytes = fileBytes;
           mimeType = "text/html";
        }

        catch(IOException ex) {
            if(!errorFile.exists()) {
                Logging.getInstance().log("(ERROR) Could not find error file: "+errorFile.toString());
                setErrorCode(500);
                String error500 = "<html><head><title>500 Internal Server Error</title></head><body><h1>500 Internal Server Error (Error File not Found)</h1></body></html>";
                contentBytes = error500.getBytes();
                contentLength = contentBytes.length;
                mimeType = "text/html";
            }

        }
        return contentBytes;
    }
}